Now that your host is in place, the final task is to build a piece of software to communicate with this WCF service type. While you could take the long road and build the necessary infrastructure by hand (a feasible, but labor-intensive task), the .NET Framework 4.0 SDK provides several approaches to generate a client-side proxy quickly. Begin by creating a new Console Application named MagicEightBallServiceClient.
The first way you can build a client-side proxy is to use the svcutil.exe command-line tool. Using svcutil.exe, you can generate a new C# language file that represents the proxy code itself, as well as a client-side configuration file. You can do this by specifying the service’s endpoint as the first parameter. You use the /out: flag to define the name of the *.cs file containing the proxy, and you use the /config: option to specify the name of the generated client-side *.config file.
Assuming your service is currently running, the following command set passed into svcutil.exe will generate two new files in the working directory (which should, of course, be entered as a single line within a Visual Studio 2010 command prompt):
svcutil http://localhost:8080/MagicEightBallService /out:myProxy.cs /config:app.config
If you open the myProxy.cs file, you will find a client-side representation of the IEightBall interface, as well as a new class named EightBallClient, which is the proxy class itself. This class derives from the generic class, System.ServiceModel.ClientBase<T>, where T is the registered service interface.
In addition to a number of custom constructors, each method of the proxy (which is based on the original interface methods) will be implemented to use the inherited Channel property to invoke the correct service method. Here is a partial snapshot of the proxy type:
[System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] public partial class EightBallClient : System.ServiceModel.ClientBase<IEightBall>, IEightBall { ... public string ObtainAnswerToQuestion(string userQuestion) { return base.Channel.ObtainAnswerToQuestion(userQuestion); } }
When you create an instance of the proxy type in your client application, the base class will establish a connection to the endpoint using the settings specified in the client-side application configuration file. Much like the server-side configuration file, the generated client-side App.config file contains an <endpoint> element and details about the basicHttpBinding used to communicate with the service.
You will also find the following <client> element, which (again) establishes the ABCs from the client’s perspective:
<client> <endpoint address="http://localhost:8080/MagicEightBallService" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IEightBall" contract="IEightBall" name="BasicHttpBinding_IEightBall" /> </client>
At this point, you could include these two files into a client project (and reference the System.ServiceModel.dll assembly), and then use the proxy type to communicate with the remote WCF service. However, you’ll take a different approach here, looking at how Visual Studio can help you further automate the creation of client-side proxy files.
Like any good command-line tool, svcutil.exe provides a great number of options that you can use to control how the client proxy is generated. If you do not require these advanced options, you can generate the same two files using the Visual Studio 2010 IDE. For the client project, simply select the Add Service Reference option from the Project menu.
Once you activate this menu option, you will be prompted to enter the service URI. At this point, click the Go button to see the service description (see Figure 25-7).
Figure 25-7 Generating the proxy files using Visual Studio 2010
Beyond creating and inserting the proxy files into your current project, this tool is kind enough to reference the WCF assemblies automatically on your behalf. In accordance with a naming convention, the proxy class is defined within a namespace called ServiceReference, which is nested in the client’s namespace (to avoid possible name clashes). Here is the complete client code:
// Location of the proxy. using MagicEightBallServiceClient.ServiceReference1; namespace MagicEightBallServiceClient { class Program { static void Main(string[] args) { Console.WriteLine("***** Ask the Magic 8 Ball *****\n"); using (EightBallClient ball = new EightBallClient()) { Console.Write("Your question: "); string question = Console.ReadLine(); string answer = ball.ObtainAnswerToQuestion(question); Console.WriteLine("8-Ball says: {0}", answer); } Console.ReadLine(); } } }
Now assume your WCF console host is running, so you can execute the client. Here is one possible response to a question I’ve been asking quite a bit during the authoring of this edition of the book (with apologies to fine folks at Apress!)
***** Ask the Magic 8 Ball ***** Your question: Will I get this book done soon? 8-Ball says: No Press any key to continue. . .
Source Code You can find the MagicEightBallServiceClient project located under the MagicEightBallServiceHTTP directory of Chapter 25.
At this point, the host and client applications are both configured to use the simplest of the HTTP-based bindings, basicHttpBinding. Recall that the benefit of offloading settings to configuration files is that you can change the underlying plumbing in a declarative manner and expose multiple bindings for the same service.
To illustrate this, you can try a little experiment. Create a new folder on your C: drive (or wherever you happen to be saving your code) named EightBallTCP; in this new folder, create two subdirectories named Host and Client.
Next, use Windows Explorer to navigate to the \bin\Debug folder of the host project and copy MagicEightBallServiceHost.exe, MagicEightBallServiceHost.exe.config, and MagicEightBallServiceLib.dll to the C:\EightBallTCP\Host folder. Now use a simple text editor to open the *.config file for editing and modify the existing contents as follows:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="MagicEightBallServiceLib.MagicEightBallService"> <endpoint address ="" binding="netTcpBinding" contract="MagicEightBallServiceLib.IEightBall"/> <host> <baseAddresses> <add baseAddress ="net.tcp://localhost:8090/MagicEightBallService"/> </baseAddresses> </host> </service> </services> </system.serviceModel> </configuration>
Essentially, this host’s *.config file strips out all the MEX settings (because you already built the proxy) and establishes that it is using the netTcpBinding binding type through a unique port. Now run the application by double-clicking the *.exe. If all is well, you should see the host output shown here:
***** Console Based WCF Host ***** ***** Host Info ***** Address: net.tcp://localhost:8090/MagicEightBallService Binding: NetTcpBinding Contract: IEightBall ********************** The service is ready. Press the Enter key to terminate service.
To complete the test, copy the MagicEightBallServiceClient.exe and MagicEightBallServiceClient.exe.config files from the \bin\Debug folder of the client application into the C:\EightBallTCP\Client folder. Update the client configuration file like this:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint address="net.tcp://localhost:8090/MagicEightBallService" binding="netTcpBinding" contract="ServiceReference1.IEightBall" name="netTcpBinding_IEightBall" /> </client> </system.serviceModel> </configuration>
This client-side configuration file is a massive simplification compared to what the Visual Studio proxy generator authored. Notice how you have completely removed the existing <bindings> element. Originally, the *.config file contained a <bindings> element with a <basicHttpBinding> sub-element that supplied numerous details of the client’s binding settings (e.g., timeouts).
The truth is you never needed that detail for this example because you automatically obtain the default values of the underlying BasicHttpBinding object. If you needed to, you could of course update the existing <bindings> element to define details of the <netTcpBinding> sub-element; however, doing so is not required if you are happy with the default values of the NetTcpBinding object.
In any case, you should now be able to run your client application. Assuming the host is still running in the background, you will be able to move data between your assemblies using TCP.
Source Code You can find the MagicEightBallTCP project under the Chapter 25 subdirectory.